import axios from 'axios'
import { $message, $loading } from '@/assets/js/utils'

class CreateApi {
	#store;
	#config;
	constructor(store,config){
		this.#store = store;
		this.#config = config;
		
		axios.interceptors.request.use(config => {
			return Promise.resolve(config);
		}, (error) => {
			console.log('Before Ajax Failed!',error)
			return Promise.reject(this.#config.ajax.errMsg);
		});
		
		axios.interceptors.response.use(
			(response)=>{
				if (response.status===200) {
					return Promise.resolve(response.data);
				} else {
					console.log('Ajax Status Error, Code: '+response.status)
					return Promise.reject(this.#config.ajax.errMsg);
				}
			},
			(error)=>{
				console.log('Ajax Failed!',error)
				return Promise.reject(this.#config.ajax.errMsg);
			}
		)
	}
	
	/*
	 内部方法，获取object对象类型
	 */
	#getObjectType(obj){
		if (typeof obj !== 'object') {
			return null;
		} else {
			let objTypeStr = Object.prototype.toString.call(obj).toLowerCase().trim();
			objTypeStr = objTypeStr.substr(1,objTypeStr.length-2)
			let tempA = objTypeStr.split(" ");
			return tempA[1];
		}	
	}
	
	/*
	内部方法，解析额外设置
	 */
	#parseThirdOptions(opts){
		const defaultOpts = {
			host:'default',
			block:'default',
			withCredentials:false,
			fullRes:false,
			loading:false
		}
		let result = {...defaultOpts}
		if (opts) {
			if (typeof opts === 'string') {
				result.block = opts
			} else if (this.#getObjectType(opts)==='object') {
				result = {...result,...opts}
			}
		} 
		return result;
	}
	
	/*
	api调用
	 */
	#api(httpMethod,uri,data={},opts,params={}){
		return new Promise((resolve, reject)=>{
			let url = this.getUrl(uri,opts,true);  //组成请求地址
			let ajaxOptions  = {
				url,
				method:httpMethod,
				withCredentials:opts.withCredentials,
				timeout:this.#config.ajax.timeout
			}
			if (httpMethod==='POST'||httpMethod==='PUT'||httpMethod==='PATCH') {
				ajaxOptions.data = data;
				if (params && Object.keys(params).length>0){
					ajaxOptions.params = params;
				}
			} else {
				//GET和DELETE方法，加时间戳
				ajaxOptions.params = {...data,...{timekey:new Date().getTime()}};
			}
			
			//-----axios start-----
			axios(ajaxOptions).then((d)=>{
				if (d.success===true && d.code===200) {
					if (opts.fullRes===true) {
						resolve(d);
					} else {
						resolve(d.data);
					}
				} else {
					let msg = d.message;
					if (!msg) msg = this.#config.ajax.errMsg
					reject(msg);
				}
			}).catch((err)=>{
				reject(err)
			})
			//-----axios end----
		})
		//-----Promise end-----
	}
	
	/*
	获取请求地址
	  method 请求的后端方法名称
		opts 求参数，JSON对象，其中 host 为public config中配置的域名名称， block 为 config文件夹中配置的接口模块名称，
		self 是否是内部调用，外部调用不传
	 */
	getUrl(method,opts,self=false){
		let res = method;
		if (!self) {
			opts = this.#parseThirdOptions(opts)
		}
		let host = '';
		if (this.#config.base && this.#config.base.host && this.#config.base.host[opts.host]) {
			host = this.#config.base.host[opts.host]
		}
		res = host + this.#config.ajax.block[opts.block] + res;
		return res;
	}
	
	/* 
	 httpMethod: get post put dellete patch
	 uri:接口方法名
	 data:传递给后端的数据（JSON）
	 opts:接口调用方法额外设置
	 params：post put时，如果需要url后面带的其他参数，JSON格式
	 */
	base(httpMethod,uri,data,opts,params){
		return new Promise((resolve, reject)=>{
			opts = this.#parseThirdOptions(opts)
			if (opts.loading===true) {
				$loading.show()
			}
			this.#api(httpMethod,uri,data,opts,params).then((d)=>{
				if (opts.loading===true) {
					$loading.hide()
				}
				resolve(d)
			}).catch(err=>{
				if (opts.loading===true) {
					$loading.hide()
				}
				$message.error(err)
				reject(err)
			})
		})
	}
}

CreateApi.prototype.get = function(method,params,opts){
	return this.base('GET',method,params,opts,{})
}
CreateApi.prototype.post = function(method,params,opts,paramsX){
	return this.base('POST',method,params,opts,paramsX)
}
CreateApi.prototype.put = function(method,params,opts,paramsX){
	return this.base('PUT',method,params,opts,paramsX)
}
CreateApi.prototype.delete = function(method,params,opts){
	return this.base('DELETE',method,params,opts,{})
}
CreateApi.prototype.patch = function(method,params,opts,paramsX){
	return this.base('PATCH',method,params,opts,paramsX)
}

export default CreateApi